import java.text.SimpleDateFormat;
import java.util.Date;

public class LogUtils {
	
	private static final String NEW_LINE = "\n";
	private static final LogUtils INSTANCE = new LogUtils();
	private static final String SYSTEM_TIMESTAMP = "yyyy-MM-dd HH:mm:ss";
	private static final short CMD_INFO = 1;
	private static final short CMD_DEBUG = 2;
	private static final short CMD_ERROR = -1;
	private static String logDetails = "";
	private static final int ROLLOVER = 307200;
	
	private LogUtils() {
		;
	}
	
	
	public static void printMemoryUsage(Class<?> classObj) {
		if (classObj == null) {
			return;
		}
		String className = classObj.getName();
		System.out.println(className + " MaxMemory @ Runtime: " + Runtime.getRuntime().maxMemory() / (1024 * 1024) + " MB");
		System.out.println(className + " FreeMemory @ Runtime: " + Runtime.getRuntime().freeMemory()  / (1024 * 1024) + " MB");
		System.out.println(className + " TotalMemory @ Runtime: " + Runtime.getRuntime().totalMemory()  / (1024 * 1024) + " MB");
	}
	
	public static LogUtils getInstance() {
		return INSTANCE;
	}
	
	private void logHelper(short cmd, String message) {
		logThread th = new logThread();
		th.setCmd(cmd);
		th.setLog(message);
		th.start();
	}
	
	public void error(Throwable t, String messageHeader) {
		String st = "";
		if (t != null) {
			t.getMessage();
			t.printStackTrace();
		}
		logHelper(CMD_ERROR, messageHeader + " : " + st);
	}
	
	public void info(String message) {
		logHelper(CMD_INFO, message);
	}
	
	public void debug(String message) {
		logHelper(CMD_DEBUG, message);
	}
	
	private static class logThread extends Thread {
		private static Byte obj = new Byte((byte) 1);
		private short cmd = 0;
		private String log;
		private final String LEFT_BRACKET = "[";
		private final String RIGHT_BRACKET = "]";
		
		public boolean isCmdError() {
			return this.cmd == CMD_ERROR; 
		}
		
		public boolean isCmdInfo() {
			return this.cmd == CMD_INFO; 
		}
		
		public boolean isCmdDebug() {
			return this.cmd == CMD_DEBUG; 
		}
		
		public short getCmd() {
			return cmd;
		}

		public void setCmd(short cmd) {
			this.cmd = cmd;
		}

		public String getLog() {
			return log;
		}

		public void setLog(String log) {
			this.log = log;
		}
		
		private String getCurrentTime() {
			Date date = new Date();
			SimpleDateFormat sdf = new SimpleDateFormat(SYSTEM_TIMESTAMP);
			String timeStamp = sdf.format(date);
			return timeStamp;
		}
		
		private void syncwrite() {
			synchronized(obj) {
				int length = logDetails.getBytes().length;
				if (length >= ROLLOVER) {
					logDetails = "";
				}
				String addLog = LEFT_BRACKET + getCurrentTime() + RIGHT_BRACKET + log + NEW_LINE;
				logDetails += addLog;
				if (this.isCmdError()) 
					System.err.print(addLog);
				else
					System.out.print(addLog);
			}
		}
		
		public void run() {
			syncwrite();
		}
	}
}